#include <stdio.h>
#include <modbus.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <errno.h>
#include <string.h>
#include "cJSON.h"
#include <stdint.h>
#include <sys/msg.h>
#include "shmat.h"
#include "msg_queue_peer.h"
#define MAX_NODE 128 // 最大支持设备数目
union data
{
    int a;
    float val;
};
struct stm32_data
{
    long a;
    int key;
    int type;
    union data val;
};
struct modbus_data
{
    long a;
    int type;
    int addr;
    int key;
    union data val;
};
struct stm32_data stm32data;
struct modbus_data modbusdata;

void *hander(void *arg)
{
    // 处理线程的代码
    modbus_t *ctx = (modbus_t *)arg;
    long modbustype = 2;
    while (1)
    {
        if (msg_queue_recv("queue", &modbusdata, sizeof(modbusdata), modbustype, 0) == -1)
        {
            perror("msg_queue_recv error");
        }
        else
        {
            printf("keys:%d newval:%d\n", modbusdata.key, modbusdata.val.a);
        }
        if (modbusdata.key == 202)
        {
            // 这里记录您要将值写入到 Modbus 设备
            int ret = modbus_write_register(ctx, 30001, modbusdata.val.a);
            if (ret == -1)
            {
                perror("modbus_write_register error");
            }
        }
        if (modbusdata.key == 204)
        {
            // 这里记录您要将值写入到 Modbus 设备
            int ret = modbus_write_bit(ctx, 40000, modbusdata.val.a);
            if (ret == -1)
            {
                perror("modbus_write_register error");
            }
        }
        sleep(1);
    }
}
float carbon;
int main(int argc, char const *argv[])
{
    const char *json_data = "{"
                            "\"version\":\"v1.0\","
                            "\"report\":{\"type\":0,\"period\":5},"
                            "\"stm32\":{\"data\":["
                            "{\"key\":101,\"name\":\"Temp\",\"type\":3,\"value\":20.3,\"newval\":30.56},"
                            "{\"key\":102,\"name\":\"Door\",\"type\":1,\"value\":1,\"newval\":0},"
                            "{\"key\":103,\"name\":\"Led1\",\"type\":1,\"value\":0,\"newval\":0},"
                            "{\"key\":104,\"name\":\"Led2\",\"type\":1,\"value\":0,\"newval\":0},"
                            "{\"key\":105,\"name\":\"Fan\",\"type\":1,\"value\":0,\"newval\":1},"
                            "{\"key\":106,\"name\":\"Ekey\",\"type\":1,\"value\":0,\"newval\":1},"
                            "{\"key\":107,\"name\":\"Hum\",\"type\":3,\"value\":20.3,\"newval\":33.9}"
                            "]},"
                            "\"modbus\":{\"data\":["
                            "{\"key\":201,\"name\":\"Etemp\",\"addr\":30000,\"type\":3,\"value\":20.3,\"newval\":30.6},"
                            "{\"key\":202,\"name\":\"Revolution\",\"addr\":30001,\"type\":1,\"value\":0,\"newval\":3000},"
                            "{\"key\":203,\"name\":\"Carbon\",\"addr\":30002,\"type\":3,\"value\":0.04,\"newval\":30.56},"
                            "{\"key\":204,\"name\":\"Mdoor\",\"addr\":40000,\"type\":1,\"value\":1,\"newval\":0}"
                            "]}}";
    modbus_t *ctx;
    ctx = modbus_new_tcp(argv[1], atoi(argv[2])); // 以TCP方式创建Modbus实例，并初始化
    if (ctx == NULL)
    {
        perror("modbus_new_tcp err");
        return -1;
    }
    if (modbus_set_slave(ctx, 1)) // 设置从机ID
    {
        perror("modbus_set_slave err");
        return -1;
    }
    if (modbus_connect(ctx)) // 和从机建立链接
    {
        perror("modbus_connect err");
        return -1;
    }

    struct shm_param para; // 共享内存结构体
    // 创建共享内存
    // 初始化
    shm_init(&para, "mqtt_json", 4096);
    // 获取共享内存指针
    char *shm_p = (char *)shm_getaddr(&para);
    // 初始化共享内存
    printf("gongxiangneicun ok\n");
    // printf("%s\n",shm_p);
    while (1)
    {
        if (NULL != shm_p)
        {
            perror("开始写数据\n");
            break;
        }
    }

    // strcpy(shm_p, json_data);

    pthread_t tid; // 线程
    pthread_create(&tid, NULL, hander, ctx);
    pthread_detach(tid);

    uint16_t etemp[3];
    uint8_t mdoor[1];
    while (1)
    {
        // 读取寄存器
        int ret = modbus_read_registers(ctx, 30000, 3, etemp);
        int ret_mdoor = modbus_read_bits(ctx, 40000, 1, mdoor);
        if (ret == -1 || ret_mdoor == -1)
        {
            fprintf(stderr, "modbus_read_registers_etmpe failed: %s\n", modbus_strerror(errno));
            return -1;
        }
        carbon = (float)etemp[2] / 100;
        // printf("cc%.2f\n",carbon);
        // printf("%04x %04x %04x %.2f\n", etemp[0], etemp[1], etemp[2],carbon); // 输出读取的寄存器值
        cJSON *root;
        root = cJSON_Parse(shm_p);
        // if (!root)
        // {
        //     const char *error_ptr = cJSON_GetErrorPtr();
        //     if (error_ptr != NULL)
        //     {
        //         fprintf(stderr, "ERROR before :%s\n", error_ptr);
        //     }
        //     return 1;
        // }

        cJSON *modbus = cJSON_GetObjectItem(root, "modbus");
        cJSON *data = cJSON_GetObjectItem(modbus, "data");
        int n = cJSON_GetArraySize(data);

        // 遍历数据项
        for (int i = 0; i < n; i++)
        {
            cJSON *item = cJSON_GetArrayItem(data, i);
            cJSON *key = cJSON_GetObjectItem(item, "key");

            if (key->valueint == 201)
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");
                if (etemp[0] != newval->valuedouble)
                {
                    cJSON_SetNumberValue(newval, etemp[0]);
                    printf("Etemp:%.2f\n", newval->valuedouble);
                }
            }
            else if (key->valueint == 202)
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");
                if (etemp[1] != newval->valuedouble)
                {
                    cJSON_SetNumberValue(newval, etemp[1]);
                    printf("Revolution:%.2f\n", newval->valuedouble);
                }
            }
            else if (key->valueint == 203)
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");
                // printf("newval->valuedouble:%f carbon:%f\n",newval->valuedouble,carbon);

                if (carbon != (float)newval->valuedouble)
                {
                    cJSON_SetNumberValue(newval, carbon);
                    printf("CO2:%.2f\n", newval->valuedouble);
                }
            }
            else if (key->valueint == 204)
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");
                // printf("newval->valuedouble:%f carbon:%f\n",newval->valuedouble,carbon);

                if (mdoor[0] != newval->valueint)
                {
                    cJSON_SetNumberValue(newval, mdoor[0]);
                    printf("Mdoor:%d\n", newval->valueint);
                }
            }
        }
        // 修改后的 JSON 数据更新到共享内存
        char *updated_json_data = cJSON_Print(root);
        if (updated_json_data == NULL)
        {
            perror("cJSON_Print failed");
            cJSON_Delete(root);
            continue;
        }
        strcpy(shm_p, updated_json_data);
        free(updated_json_data);
        updated_json_data = NULL;
        cJSON_Delete(root);

        sleep(2);
    }

    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}